# SQLAchemy models

from datetime import datetime
from flask import current_app
from app import db, redis_client, ma
from marshmallow import fields

# 基表
class BaseModel(db.Model):
    __abstract__ = True # 抽象类

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    created_at = db.Column(db.DateTime, default=datetime.now) # 创建时间, 默认为当前时间
    updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now) # 更新时间, 默认为创建时间, 当数据更新时, 更新为当前时间

    is_delete = db.Column(db.Boolean, default=False) # 逻辑删除, 默认未删除
    deleted_at = db.Column(db.DateTime)

    def delete(self, soft=True):
        if soft:
            self.is_delete = True
            self.deleted_at = datetime.now()
            db.session.commit()
        else: # 硬删除
            db.session.delete(self) 

            db.session.commit()
    

# 用户表
class User(BaseModel):
    id = db.Column(db.Integer, primary_key=True)
    user_name = db.Column(db.String(64), unique=True, nullable=False) # nullable=False 不允许为空
    password = db.Column(db.String(256), nullable=False)

# 用户信息表
class UserInfo(BaseModel):
    #显示定义表名
    __tablename__ = 'userinfo'

    id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) #
    # id = db.Column(db.Integer, db.ForeignKey('user.id'))
    nickname = db.Column(db.String(64), nullable=False)
    gender = db.Column(db.Enum('male', 'female'), default='male')
    country = db.Column(db.Enum('China', 'USA', 'Japan'), default='China')
    email = db.Column(db.String(64))
    bro = db.Column(db.String(512)) # 个人简介
    avatar = db.Column(db.String(256)) # 头像

    @property
    def is_isonline(self):
        return redis_client.hget('online_users', self.id) is not None

class UserInfoSchema(ma.SQLAlchemyAutoSchema):
    id = fields.Int() # 显示定义id字段类型，不然当id既为主键，又是外建，会报错
    class Meta:
        model = UserInfo
        fields = ('id', 'nickname', 'avatar')

# 聊天室表
class Chatroom(BaseModel):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(64), unique=True, nullable=False)
    is_private = db.Column(db.Boolean, default=False)
    creator_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    last_activity_time = db.Column(db.DateTime, default=datetime.now)

# 聊天室用户表
class ChatroomMember(BaseModel):
    __tablename__ = 'chatroom_member'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    chatroom_id = db.Column(db.Integer, db.ForeignKey('chatroom.id', ondelete="CASCADE"))
    user_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))

# 聊天记录表flask db migrate -m "Add ondelete cascade to chatroom relations"
class ChatroomMessage(BaseModel):
    __tablename__ = 'chatroommessage'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    chatroom_id = db.Column(db.Integer, db.ForeignKey('chatroom.id', ondelete="CASCADE"))
    sender_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))
    content = db.Column(db.Text, nullable=False)

    is_recalled = db.Column(db.Boolean, default=False) # 是否是撤回消息
    recalled_time = db.Column(db.DateTime)

    sender = db.relationship('UserInfo', foreign_keys=[sender_id]) # foreign_keys: 指定哪
    chatroom = db.relationship('Chatroom', foreign_keys = [chatroom_id], lazy = 'joined', backref = 'chats') # 在Chatroom模型中添加一个属性chats, lazy = 'dynamic' 执行动态加载

    __table_args__ = (
        db.Index('idx_chatroom_id_created_at', 'chatroom_id', 'created_at'),
    )

    @property
    def sender_nickname(self):
        return self.sender.nickname
    
    @property
    def sender_avatar(self):
        return self.sender.avatar
    
# 朋友消息表
class FriendMessage(BaseModel):
    __tablename__ = 'friendmessage'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text, nullable=False)

    sender_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))
    receiver_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))

    is_recalled = db.Column(db.Boolean, default=False)
    recall_time = db.Column(db.DateTime)

    __table_args__ = (
        db.Index('idx_sender_receiver_created_at', 'sender_id', 'receiver_id', 'created_at'), # 建立多级索隐，左匹配原则
    )

    @property
    def sender_nickname(self):
        return self.sender.nickname
    
    @property
    def sender_avatar(self):
        return self.sender.avatar

# 朋友列表
class Friendships(BaseModel):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))
    friend_id = db.Column(db.Integer, db.ForeignKey('userinfo.id'))

    last_activity_time = db.Column(db.DateTime, default=datetime.now) # 最晚互动时间
    last_message_id = db.Column(db.Integer, db.ForeignKey('friendmessage.id'))
    last_read_message_id = db.Column(db.Integer, db.ForeignKey('friendmessage.id')) # id 阅读 friend_id 最后一条消息的id

    unread_count = db.Column(db.Integer, default=0) # 未阅读消息数

    friend = db.relationship('UserInfo', foreign_keys=[friend_id])


# 好友申请列表
class FriendRequest(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    sender_name = db.Column(db.String(64), db.ForeignKey('user.user_name'))
    receiver_name = db.Column(db.String(64), db.ForeignKey('user.user_name'))

    time = db.Column(db.DateTime, default=datetime.now)
    status = db.Column(db.Integer, default=0) # 0: 等待处理 1: 已同意 2: 已拒绝